/*
 *
 * Copyright (C) 2012 Walter Lütgenau
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *      http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 * 
 */
package offset.nodes.client.chooser.view;

import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.Transferable;
import java.awt.datatransfer.UnsupportedFlavorException;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JComponent;
import javax.swing.JTree;
import javax.swing.TransferHandler;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.TreePath;
import offset.nodes.client.tree.view.TreeConfiguratorPanel;

/**
 *
 * @author Walter Lütgenau
 */
public class ReorderTreeNodeTransferHandler extends TransferHandler {

    protected DataFlavor treeNodeDataFlavor = null;
    List<DefaultMutableTreeNode> parents = new ArrayList<DefaultMutableTreeNode>();

    class TreeNodesTransferable implements Transferable {
        DefaultMutableTreeNode[] nodes;

        public TreeNodesTransferable(DefaultMutableTreeNode[] nodes) {
            this.nodes = nodes;
        }

        @Override
        public Object getTransferData(DataFlavor flavor) throws UnsupportedFlavorException, IOException {
            return nodes;
        }

        public List<DefaultMutableTreeNode> getParents() {
            return parents;
        }
        
        @Override
        public DataFlavor[] getTransferDataFlavors() {
            return new DataFlavor[] { treeNodeDataFlavor };
        }

        @Override
        public boolean isDataFlavorSupported(DataFlavor flavor) {
            return flavor.equals(treeNodeDataFlavor);
        }

        public DefaultMutableTreeNode[] getNodes() {
            return nodes;
        }

    }

    public ReorderTreeNodeTransferHandler() {
        try {
            treeNodeDataFlavor = new DataFlavor(DataFlavor.javaJVMLocalObjectMimeType + ";class=\"" + DefaultMutableTreeNode[].class.getName() + "\"");
        } catch (ClassNotFoundException ex) {
            Logger.getLogger(ReorderTreeNodeTransferHandler.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    public List<DefaultMutableTreeNode> getParents() {
        return parents;
    }

    @Override
    protected void exportDone(JComponent source, Transferable data, int action) {
        if (action != MOVE)
            return;

        JTree tree = (JTree) source;
        DefaultMutableTreeNode[] nodes = ((TreeNodesTransferable) data).getNodes();

        /*for (DefaultMutableTreeNode node : nodes)
            ((DefaultTreeModel) tree.getModel()).removeNodeFromParent(node);*/

        DefaultMutableTreeNode parent = (DefaultMutableTreeNode) nodes[0].getParent();
        ((DefaultTreeModel) tree.getModel()).nodeChanged(parent);
        
        parents.add(parent);
    }

    @Override
    protected Transferable createTransferable(JComponent c) {
        JTree tree = (JTree) c;

        StringBuilder buf = new StringBuilder();

        DefaultMutableTreeNode[] nodes = new DefaultMutableTreeNode[tree.getSelectionPaths().length];
        for (int i = 0; i < tree.getSelectionPaths().length; i++) {
            DefaultMutableTreeNode selected = (DefaultMutableTreeNode) tree.getSelectionPaths()[i].getLastPathComponent();
            nodes[i] = selected;
        }

        return new TreeNodesTransferable(nodes);
    }

    @Override
    public int getSourceActions(JComponent c) {
        return COPY_OR_MOVE;
    }

    @Override
    public boolean canImport(javax.swing.TransferHandler.TransferSupport transfersupport) {
        if (!transfersupport.isDrop())
            return false;

        if (!transfersupport.isDataFlavorSupported(treeNodeDataFlavor))
            return false;
        else {
            try {
                javax.swing.JTree.DropLocation droplocation = (javax.swing.JTree.DropLocation) transfersupport.getDropLocation();
                TreePath path = droplocation.getPath();
                if (path == null)
                    return false;
                DefaultMutableTreeNode[] nodes = (DefaultMutableTreeNode[]) transfersupport.getTransferable().getTransferData(treeNodeDataFlavor);
                DefaultMutableTreeNode dropTarget = (DefaultMutableTreeNode) path.getLastPathComponent();

                for (DefaultMutableTreeNode node : nodes)
                    if (!node.getParent().equals(dropTarget))
                        return false;

                return true;
            } catch (UnsupportedFlavorException ex) {
                Logger.getLogger(TreeConfiguratorPanel.class.getName()).log(Level.SEVERE, null, ex);
            } catch (IOException ex) {
                Logger.getLogger(TreeConfiguratorPanel.class.getName()).log(Level.SEVERE, null, ex);
            }

            return false;
        }
    }

    @Override
    public boolean importData(javax.swing.TransferHandler.TransferSupport transfersupport) {
        try {
            if (!canImport(transfersupport))
                return false;

            javax.swing.JTree.DropLocation droplocation = (javax.swing.JTree.DropLocation) transfersupport.getDropLocation();
            TreePath treepath = droplocation.getPath();

            DefaultMutableTreeNode[] nodes = (DefaultMutableTreeNode[]) transfersupport.getTransferable().getTransferData(treeNodeDataFlavor);
            int position = droplocation.getChildIndex();

            JTree tree = (JTree) transfersupport.getComponent();
            if (position == -1)
                position = tree.getModel().getChildCount(treepath.getLastPathComponent());
            
            DefaultMutableTreeNode dropTarget = (DefaultMutableTreeNode) treepath.getLastPathComponent();
            boolean up = false;
            if (position < dropTarget.getIndex(nodes[0]))
                up = true;
            for (int i = 0; i < nodes.length; i++) {
                ((DefaultTreeModel) tree.getModel()).removeNodeFromParent(nodes[i]);
                ((DefaultTreeModel) tree.getModel()).insertNodeInto(nodes[i], dropTarget, up ? position + i : position - 1);
            }

            ((DefaultTreeModel) tree.getModel()).nodeChanged(dropTarget);

            return true;
        } catch (UnsupportedFlavorException ex) {
            Logger.getLogger(ReorderTreeNodeTransferHandler.class.getName()).log(Level.SEVERE, null, ex);
        } catch (IOException ex) {
            Logger.getLogger(ReorderTreeNodeTransferHandler.class.getName()).log(Level.SEVERE, null, ex);
        }

        return false;
    }
}
